Documentation References: 1) ug361.pdf: "Virtex-6 FPGA SelectIO Resources" 2) ug362.pdf: "Virtex-6 FPGA Clocking Resources" The relevant IPs that should be changed to Virtex-6 specific IPs: A) DCM: clocking B) IODELAY/IDELAY C) IDDR: Double Data Rate, ADC serial decode D) FIFO Generator E) Memory Generator A) Clocking Resources Current firmware uses DCM to generate all derived clocks. Virtex 6 has a new IP: "Mixed Mode Clock Manager": MMCM_ADV or MMCM_BASE Example use: The following instance provides 3 ouput clocks: 200MHz on CLKOUT0 160MHz on CLKOUT1 100MHz on CLKOUT2 mmcm_adv_inst : MMCM_ADV GENERIC MAP ( BANDWIDTH => "OPTIMIZED", CLKOUT4_CASCADE => false, CLOCK_HOLD => false, COMPENSATION => "ZHOLD", STARTUP_WAIT => false, DIVCLK_DIVIDE => 1, CLKFBOUT_MULT_F => 16.000, CLKFBOUT_PHASE => 0.000, CLKFBOUT_USE_FINE_PS => false, CLKOUT0_DIVIDE_F => 4.000, CLKOUT0_PHASE => 0.000, CLKOUT0_DUTY_CYCLE => 0.500, CLKOUT0_USE_FINE_PS => false, CLKOUT1_DIVIDE => 5, CLKOUT1_PHASE => 0.000, CLKOUT1_DUTY_CYCLE => 0.500, CLKOUT1_USE_FINE_PS => false, CLKOUT2_DIVIDE => 8, CLKOUT2_PHASE => 0.000, CLKOUT2_DUTY_CYCLE => 0.500, CLKOUT2_USE_FINE_PS => false, CLKIN1_PERIOD => 20.000, REF_JITTER1 => 0.010 ) PORT MAP ( CLKFBOUT => clkfbout, CLKFBOUTB => clkfboutb_unused, CLKOUT0 => clkout0, -- 200 MHz CLKOUT0B => clkout0b_unused, CLKOUT1 => clkout1, -- 160 MHz CLKOUT1B => clkout1b_unused, CLKOUT2 => clkout2, -- 100 MHz CLKOUT2B => clkout2b_unused, CLKOUT3 => clkout3_unused, CLKOUT3B => clkout3b_unused, CLKOUT4 => clkout4_unused, CLKOUT5 => clkout5_unused, CLKOUT6 => clkout6_unused, -- Input clock control CLKFBIN => clkfbout, CLKIN1 => clkin1, CLKIN2 => '0', -- Tied to always select the primary input clock CLKINSEL => '1', -- Ports for dynamic reconfiguration DADDR => (OTHERS => '0'), DCLK => '0', DEN => '0', DI => (OTHERS => '0'), DO => do_unused, DRDY => drdy_unused, DWE => '0', -- Ports for dynamic phase shift PSCLK => '0', PSEN => '0', PSINCDEC => '0', PSDONE => psdone_unused, -- Other control and status signals LOCKED => LOCKED, CLKINSTOPPED => clkinstopped_unused, CLKFBSTOPPED => clkfbstopped_unused, PWRDWN => '0', RST => RESET ); -- Output buffering ------------------------------------- clkout1_buf : BUFG PORT MAP ( O => CLK_OUT1, I => clkout1); ISE generates MMCM_ADV instances, but by hand it might be easier to use MMCM_BASE. MMCM_ADV is a superset of MMCM_BASE. B) IODELAY: input or output delays Current firmware uses: IDELAY IODELAY Virtex-6 provides a new IP: IODELAYE1 Can now be used for both Input or Output delays. Can be controlled in 3 different ways: FIXED: a fixed delay VARIABLE: a delay value can be dynamically adjusted while running (via CE and INC) VAR_LOADABLE: a fixed delay value can be loaded while running (via RST and CNTVALUEIN) Difference to previous IODELAY: now there are only 31 delay taps. Each tap is about 78ps for a 200MHz control frequency IODLAY Resolution = 1/(32 x 2 x Fref) = 1/(64 x 200MHz) = 78.125ps Can be configured either input or output delay, or input and output delay Looks like the control of the delay is regional, so one might need several IDELAYCTRL (?) Connected via the IODELAY_GROUP contraint (?) Example use: a variable loadable Input delay: attribute IODELAY_GROUP : string; attribute IODELAY_GROUP of delayctrl : label is "ttt_group"; delayctrl : IDELAYCTRL port map ( RDY => DELAY_LOCKED, REFCLK => REF_CLOCK, RST => IO_RESET ); ibufds_inst : IBUFDS generic map ( DIFF_TERM => TRUE, -- Differential termination IOSTANDARD => "LVDS_25") port map ( I => DATA_IN_FROM_PINS_P (pin_count), IB => DATA_IN_FROM_PINS_N (pin_count), O => data_in_from_pins_int(pin_count)); attribute IODELAY_GROUP of iodelay_bus: label is "ttt_group"; iodelay_bus : IODELAYE1 generic map ( CINVCTRL_SEL => FALSE, -- TRUE, FALSE DELAY_SRC => "I", -- I, IO, O, CLKIN, DATAIN HIGH_PERFORMANCE_MODE => TRUE, -- TRUE, FALSE IDELAY_TYPE => "VAR_LOADABLE", -- FIXED, DEFAULT, VARIABLE, or VAR_LOADABLE IDELAY_VALUE => 0, -- 0 to 31 ODELAY_TYPE => "FIXED", -- Has to be set to FIXED when IODELAYE1 is configured for Input ODELAY_VALUE => 0, -- Set to 0 as IODELAYE1 is configured for Input REFCLK_FREQUENCY => 200.0, SIGNAL_PATTERN => "DATA" -- CLOCK, DATA ) port map ( DATAOUT => data_delay (pin_count), DATAIN => '0', -- Data from FPGA logic C => DELAY_CLK, CE => delay_ce(pin_count), --DELAY_DATA_CE, INC => delay_inc_dec(pin_count), --DELAY_DATA_INC, IDATAIN => data_in_from_pins_int (pin_count), -- Driven by IOB ODATAIN => '0', RST => DELAY_RESET, T => '1', CNTVALUEIN => intap(pin_count), --DELAY_TAP_IN, CNTVALUEOUT => outtap(pin_count), --DELAY_TAP_OUT, CLKIN => '0', CINVCTRL => '0' ); C) ADC Serial Data Decode The ADC AD5272 digital data comes to the FPGA serialized in 12 bits on both edges of the clock. The current firmware uses a series of IPs to decode these data: IBUFDS (differential to serial), IDELAY (delay adjustment), IDDR (double data rate decoder) and then finally a state machine to re-assemble the data Virtex-6 provides an IP called ISERDESE1 "Input Serial/Deserializer" which includes all of these elements in on of the IOLOGIC regions associated with the pins for more reliable timing results. This primitive also includes a BITSLIP component to adjust the timing to the correct "bit phase". Unfortunately, the primitive doesn't provide enough bits to do all 12 bits at once, it only provides 6 bits (or 8 bits if chained, not useful for us). But one can use a latch or shift register after the ISERDESE1 to store 6 bits at a time, and thus reassemble the full 12 bits in 2 steps. Probably still need an IODELAYE1 to fine adjust the timing. (Needs to be worked out a little more in detail with use case). Here is an example from my Virtex 5 code: -- 12-bit parallel output data parallel_data <= s_p_data & s_shifted; -- 6bit shift register: PROCESS(clk_des) IS BEGIN IF rising_edge(clk_des) THEN s_shifted <= s_p_data; END IF; END PROCESS; ISERDES_even : ISERDES_NODELAY GENERIC MAP ( BITSLIP_ENABLE => true, -- TRUE/FALSE to enable bitslip controller DATA_RATE => "DDR", -- Specify data rate of "DDR" or "SDR" DATA_WIDTH => 6, -- Specify data width - INTERFACE_TYPE => "NETWORKING", -- Use model - "MEMORY" or "NETWORKING" NUM_CE => 2, -- Define number or clock enables to an integer of 1 or 2 SERDES_MODE => "MASTER") -- Set SERDES mode to "MASTER" or "SLAVE" PORT MAP ( Q1 => s_p_data(5), -- 1-bit registered SERDES output Q2 => s_p_data(4), -- 1-bit registered SERDES output Q3 => s_p_data(3), -- 1-bit registered SERDES output Q4 => s_p_data(2), -- 1-bit registered SERDES output Q5 => s_p_data(1), -- 1-bit registered SERDES output Q6 => s_p_data(0), -- 1-bit registered SERDES output SHIFTOUT1 => OPEN, -- 1-bit cascade Master/Slave output SHIFTOUT2 => OPEN, -- 1-bit cascade Master/Slave output BITSLIP => s_bitslip_en, -- 1-bit Bitslip enable input CE1 => '1', -- 1-bit clock enable input CE2 => '1', -- 1-bit clock enable input CLK => clk_data, -- 1-bit master clock input CLKB => NOT clk_data, -- 1-bit master clock input CLKDIV => clk_des, -- 1-bit divided clock input D => s_adc_data, -- 1-bit data input, connects to IODELAY or input buffer OCLK => '0', -- 1-bit fast output clock input RST => s_bitslip_reset, -- 1-bit asynchronous reset input SHIFTIN1 => '0', -- 1-bit cascade Master/Slave input SHIFTIN2 => '0' -- 1-bit cascade Master/Slave input ); D) Memory and FIFOs Virtex-6 IPs provide memory and FIFO generators that are more customized. One should use those for internal memory. (Fill in more detail here).